package com.dx.mes.service.process.service;

import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.List;

import com.dx.common.table.ppt.*;
import org.apache.commons.lang.StringUtils;
import org.hibernate.LockMode;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import com.dx.mes.common.dao.IBisDataDao;
import com.dx.mes.common.dao.IRetBoxDao;
import com.dx.mes.common.dao.IRetBoxXfrDao;
import com.dx.mes.common.dao.IRetPrdInfoDao;
import com.dx.mes.common.dao.IRetToolStDao;
import com.dx.mes.common.dao.IRetWODao;
import com.dx.mes.common.table.rtnBean.NotFoundRtnBeen;
import com.dx.mes.common.table.rtnBean.SimpleRtnBeen;
import com.dx.mes.common.transcoder.util.AppContext;
import com.dx.mes.common.transcoder.util.GUIDGenerator;
import com.dx.mes.common.transcoder.util.JacksonUtil;
import com.dx.mes.common.transcoder.util.LogUtils;
import com.dx.mes.common.transcoder.util.Util;
import com.dx.mes.facade.process.service.IFpppnloutService;
import com.dx.mes.facade.process.tx.Fpppnlout.FpppnloutI;
import com.dx.mes.facade.process.tx.Fpppnlout.FpppnloutIA;
import com.dx.mes.facade.process.tx.Fpppnlout.FpppnloutO;

import static com.dx.mes.common.bean.def.GenericDef.*;
import static com.dx.mes.common.bean.def.GenericDef.PRD_GRADE_MIX;


@Service("fpppnloutService")
public class FpppnloutService implements IFpppnloutService{
	private LogUtils logUtils;

	@Autowired
	private IRetBoxDao retBoxDao;
	@Autowired
	private IRetWODao retWoDao;
	@Autowired
	private IRetPrdInfoDao retPrdInfoDao;
	@Autowired
	private IBisDataDao bisDataDao;
	@Autowired
	private IRetToolStDao retToolStDao;
	@Autowired
	private IRetBoxXfrDao retBoxXfrDao;
	public String subMainProc(String evt_no,String strInMsg) {
		AppContext.clear();
		AppContext.setCurrServiceName(FpppnloutService.class.getSimpleName());
		AppContext.setCurrEventNumber(evt_no);
		logUtils = new LogUtils(FpppnloutService.class);
		logUtils.info("[InTrx:" + strInMsg + "]");

		String strOutMsg = null;
		FpppnloutI inTrx = new FpppnloutI();
		FpppnloutO outTrx = new FpppnloutO();

		outTrx.setTrx_id(T_FPPPNLOUT);
		outTrx.setType_id(TRX_OUT);
		outTrx.setRtn_code(RETURN_CODE_SET_ERROR);
		try {
			inTrx = JacksonUtil.fromJson(strInMsg, FpppnloutI.class);

			outTrx = subMainProc2(inTrx);
			if (RETURN_CODE_OK.equals(outTrx.getRtn_code())) {
				retPrdInfoDao.flushCurSession();
			} else {
				TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
			}
		} catch (Exception ex) {
			outTrx.setRtn_code(RETURN_CODE_UNKNOWN);
			outTrx.setRtn_mesg(ex.getCause().toString());
			TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
		} finally {
			strOutMsg = JacksonUtil.toJSONStr(outTrx);
			logUtils.info("[OutTrx:" + strOutMsg + "]");
		}
		return strOutMsg;
	}

	/**
	 * All move in logic
	 *
	 * @return
	 */
	private FpppnloutO subMainProc2(FpppnloutI inTrx) {
		Timestamp gEvtTimestamp = Util.getCurrentTimestamp();
		Double gEvtTimeD = Util.getDoubleTime();
		String gEvtSeqID = GUIDGenerator.javaGUID();
		FpppnloutO outTrx = new FpppnloutO();
		outTrx.setTrx_id(T_FPPPNLOUT);
		outTrx.setType_id(TRX_OUT);

		SimpleRtnBeen rtnBeen = new SimpleRtnBeen(_NORMAL);
		Ret_box ret_box = new Ret_box();
//		List<Ret_prd_info> gRet_prd_infoList = new ArrayList<Ret_prd_info>();
		int chip_qty = 0;
		// Check inTrx items
		rtnBeen = checkInTtx(inTrx);
		if (rtnBeen.getlRc() != _NORMAL) {
			outTrx.setRtn_code(rtnBeen.getlRc() + "");
			outTrx.setRtn_mesg(rtnBeen.getMsgBuf());
			return outTrx;
		}
		//Check operation tool status
		Ret_tool_st gRet_tool_st = new Ret_tool_st();
		gRet_tool_st = retToolStDao.get(inTrx.getTool_id());
		if (gRet_tool_st == null) {
			outTrx.setRtn_code(E_RET_TOOL_ST + E_READ_NOT_FOUND + "");
			outTrx.setRtn_mesg(new NotFoundRtnBeen(inTrx.getTool_id(), Ret_tool_st.class).toString());
			return outTrx;
		}
		//OPI Operation not need check tool status
		if(inTrx.getOpi_ope_flg() == null || !inTrx.getOpi_ope_flg().equals(_YES)){
			if(!gRet_tool_st.getTool_stat().equals(TOOL_STAT_RUN) && !gRet_tool_st.getTool_stat().equals(TOOL_STAT_IDLE)){
				outTrx.setRtn_code(E_FPPPNLOUT_TOOL_STATUS_INVALIED+ "");
				outTrx.setRtn_mesg("设备 [" + inTrx.getTool_id() + "]状态["+gRet_tool_st.getTool_stat()+"]不符，必须是RUN或IDLE才可以RUN货，请检查!");
				return outTrx;
			}
		}
		// Check box
		rtnBeen = checkRetBox(inTrx);
		if (rtnBeen.getlRc() != _NORMAL) {
			outTrx.setRtn_code(rtnBeen.getlRc() + "");
			outTrx.setRtn_mesg(rtnBeen.getMsgBuf());
			return outTrx;
		} else {
			ret_box = (Ret_box) rtnBeen.getObj();
		}

		// Check sht & Save judge info
		rtnBeen = checkAndSetRetPrdInfo(ret_box, inTrx, gEvtTimestamp, gEvtTimeD, gEvtSeqID);
		if (rtnBeen.getlRc() != _NORMAL) {
			outTrx.setRtn_code(rtnBeen.getlRc() + "");
			outTrx.setRtn_mesg(rtnBeen.getMsgBuf());
			return outTrx;
		} else {
			chip_qty = Integer.valueOf(rtnBeen.getObj().toString());
			ret_box.setChip_qty(ret_box.getChip_qty() + chip_qty);
		}

		// Update prd info -> into box
		rtnBeen = updateRetBoxInfo(ret_box, inTrx, gEvtTimestamp);
		if (rtnBeen.getlRc() != _NORMAL) {
			outTrx.setRtn_code(rtnBeen.getlRc() + "");
			outTrx.setRtn_mesg(rtnBeen.getMsgBuf());
			return outTrx;
		}else{
			outTrx.setWo_id(ret_box.getWo_id_fk());
			outTrx.setBox_id(ret_box.getBox_id());
			outTrx.setPrd_qty(ret_box.getPrd_qty().toString());
			outTrx.setEvt_user(inTrx.getEvt_usr());
			outTrx.setTool_id(inTrx.getTool_id());
			outTrx.setEvt_timestamp(gEvtTimestamp);
		}

		//update ret_tool_st LD_LAST_FETCH_TIMESTAMP
		gRet_tool_st.setUl_last_fetch_timestamp(gEvtTimestamp);
		gRet_tool_st.setEvt_timestamp(gEvtTimestamp);
		gRet_tool_st.setEvt_usr(inTrx.getEvt_usr());
		retToolStDao.update(gRet_tool_st);

		outTrx.setRtn_code(RETURN_CODE_OK);
		outTrx.setRtn_mesg(RETURN_MESG_OK);
		return outTrx;
	}

	/**
	 * Check inTrx items
	 *
	 * @return
	 */
	private SimpleRtnBeen checkInTtx(FpppnloutI inTrx) {
		String gszMsgBuf = "";

		if (Util.isSpaceCheck(inTrx.getBox_id())) {
			gszMsgBuf = "Box ID can't be null![" + inTrx.getBox_id() + "]";
			return new SimpleRtnBeen(E_FPPPNLOUT_INPUT_ITEM_EMPT, gszMsgBuf);
		}
		if (Util.isSpaceCheck(inTrx.getEvt_usr())) {
			gszMsgBuf = "User ID can't be null![" + inTrx.getEvt_usr() + "]";
			return new SimpleRtnBeen(E_FPPPNLOUT_INPUT_ITEM_EMPT, gszMsgBuf);
		}
		if (null == inTrx.getPrd_cnt() || 0 >= inTrx.getPrd_cnt()) {
			gszMsgBuf = "Panel count [" + inTrx.getPrd_cnt() + "] is invalid!";
			return new SimpleRtnBeen(E_FPPPNLOUT_INPUT_ITEM_EMPT, gszMsgBuf);
		}

		return new SimpleRtnBeen(_NORMAL);
	}

	/**
	 * Get & chk box info
	 *
	 * @param boxId
	 * @return
	 */
	private SimpleRtnBeen checkRetBox(FpppnloutI inTrx) {
		String gszMsgBuf = "";
		String boxId = inTrx.getBox_id();
		Ret_box ret_box = new Ret_box();
		SimpleRtnBeen retBeen=null;
		ret_box = retBoxDao.getWithLock(boxId, LockMode.UPGRADE);
		if (null == ret_box) {
			gszMsgBuf = new NotFoundRtnBeen(boxId, Ret_box.class).toString();
			return new SimpleRtnBeen(E_RET_BOX + E_READ_NOT_FOUND, gszMsgBuf);
		}
		if (!PROC_EMPTY.equals(ret_box.getBox_stat()) && !PROC_IN_PROCESS.equals(ret_box.getBox_stat())) {
			gszMsgBuf = "箱子 [" + ret_box.getBox_id() + "] " + "的状态为 ["
					+ ret_box.getBox_stat() + "], " + ",必须是[" + PROC_EMPTY + "]或者["+PROC_IN_PROCESS+"]!";
			return new SimpleRtnBeen(E_FPPPNLOUT_INVALID_BOX_STATUS, gszMsgBuf);
		}

		if (!_YES.equals(ret_box.getValid_flg())) {
			gszMsgBuf = "箱子 [" + ret_box.getBox_id() + "] 无效!";
			return new SimpleRtnBeen(E_FPPPNLOUT_BOX_INVALIED, gszMsgBuf);
		}
		/**
		 * 检查该卡匣是否已经被派工到机台端口上，若是，则OPI端不可以操作该卡匣
		 * important！
		 */
		if(inTrx.getOpi_ope_flg().equals(_YES)){
			Ret_box_xfr ret_box_xfr = retBoxXfrDao.get(ret_box.getBox_id());
			if(ret_box_xfr != null){
				if(("5").equals(ret_box_xfr.getXfr_stat())){
					gszMsgBuf = "该卡匣 [" + ret_box.getBox_id() + "]在设备Port上，请检查!";
					return new SimpleRtnBeen(E_FPPUPKCLM_BOX_POSITION_ERROR, gszMsgBuf);

				}
			}
		}
		//check slot_no already exists
		List<Ret_prd_info> ret_prd_infos = new ArrayList<Ret_prd_info>();
		ret_prd_infos = retPrdInfoDao.getShtListInfo(ret_box.getBox_id());
		if(ret_prd_infos != null && !ret_prd_infos.isEmpty()){
			List<FpppnloutIA> iaryAlist = new ArrayList<FpppnloutIA>();
			iaryAlist = inTrx.getIary();
			for (Ret_prd_info ret_prd_info : ret_prd_infos) {
				String slotNo = ret_prd_info.getSlot_no();
				for(FpppnloutIA iary : iaryAlist){
					String inTrxSlotNo = iary.getSlot_no();
					if(StringUtils.isNotEmpty(inTrxSlotNo)){
						if(slotNo.equals(inTrxSlotNo)){
							gszMsgBuf = "箱子 [" + ret_box.getBox_id() + "]子格位["+slotNo+"]已有玻璃！";
							return new SimpleRtnBeen(E_FPPPNLOUT_BOX_IS_FULL, gszMsgBuf);
						}
					}
				}
			}
		}


		//获取 box for prd max count
		String hql = "From Bis_data where data_cate='BXSC' AND data_ext='"+ret_box.getBox_set_code()+"'";
		List<Bis_data> bisDataList = bisDataDao.find(hql);
		int maxCnt = Integer.valueOf( bisDataList.get(0).getExt_1() );

		if (ret_box.getPrd_qty() == maxCnt) {
			gszMsgBuf = "箱子 [" + ret_box.getBox_id() + "] 已满!";
			return new SimpleRtnBeen(E_FPPPNLOUT_BOX_IS_FULL, gszMsgBuf);
		}
		if (ret_box.getPrd_qty() + inTrx.getPrd_cnt() > maxCnt ) {
			gszMsgBuf = "箱子 [" + ret_box.getBox_id() + "] 当前的产品数量为["
					+ ret_box.getPrd_qty() + "], 转入数量为 [" + inTrx.getPrd_cnt()
					+ "],超出最大数量["+maxCnt+"]";
			return new SimpleRtnBeen(E_FPPPNLOUT_BOX_WILL_FULL, gszMsgBuf);
		}

		if (0 == ret_box.getPrd_qty()) {
			if (!EMPTY_CARRIER.equals(ret_box.getReal_emp())) {
				gszMsgBuf = "箱子 [" + ret_box.getBox_id()
						+ "] 的产品数量为 0, 但箱子的real_emp非Y!";
				return new SimpleRtnBeen(E_FPPPNLOUT_BOX_NOT_REAL_EMPT, gszMsgBuf);
			}
		}
		//Check Box Category match or not
		retBeen = checkCstCate4Ope(ret_box, inTrx.getTool_id());
		if (retBeen.getlRc() != _NORMAL) {
			return new SimpleRtnBeen(retBeen.getlRc(), retBeen.getMsgBuf());
		}
		return new SimpleRtnBeen(ret_box);
	}

	/**
	 * Get & chk & set prd info
	 *
	 * @return
	 */
	private SimpleRtnBeen checkAndSetRetPrdInfo(Ret_box ret_box, FpppnloutI inTrx,
												Timestamp gEvtTimestamp, Double gEvtTimeD, String gEvtSeqID) {
		String gszMsgBuf = "";
		SimpleRtnBeen rtnBeen = new SimpleRtnBeen();
		rtnBeen.setlRc(_NORMAL);
		List<Ret_prd_info> ret_prd_infos = new ArrayList<Ret_prd_info>();
		ret_prd_infos = retPrdInfoDao.getShtListInfo(ret_box.getBox_id());
		List<FpppnloutIA> iaryAlist = new ArrayList<FpppnloutIA>();
		iaryAlist = inTrx.getIary();
		int prdCnt = inTrx.getPrd_cnt();
		int i = 0;
		int chip_qty =0;
		if (0 == prdCnt) {
			gszMsgBuf = "转入产品数量为 0!";
			return new SimpleRtnBeen(E_FPPPNLOUT_PRD_CNT_INVALIED, gszMsgBuf);
		}
		for(i=0;i<prdCnt;i++){
			FpppnloutIA iaryA = iaryAlist.get(i);
			Ret_prd_info ret_prd_info = retPrdInfoDao.get(iaryA.getPrd_seq_id());
			if(ret_prd_info == null){
				gszMsgBuf = "玻璃代码["+iaryA.getPrd_seq_id()+"]不存在！";
				return new SimpleRtnBeen(E_RET_PRD_INFO + E_READ_NOT_FOUND, gszMsgBuf);
			}
			// Must INPR
			if (!PROC_IN_PROCESS.equals(ret_prd_info.getPrd_stat())) {
				gszMsgBuf = "状态为 [" + ret_prd_info.getPrd_stat() + "] ,必须为 ["
						+ PROC_IN_PROCESS + "]";
				return new SimpleRtnBeen(E_FPPPNLOUT_INVALIED_PRD_STAT, gszMsgBuf);
			}
			// Box ID must space
			if (!Util.isSpaceCheck(ret_prd_info.getBox_id_fk())) {
				gszMsgBuf = "产品 [" + ret_prd_info.getPrd_seq_id() + "] 已经转入 ["
						+ ret_prd_info.getBox_id_fk() + "]";
				return new SimpleRtnBeen(E_FPPPNLOUT_PRD_ALREADY_IN_BOX, gszMsgBuf);
			}
			if(BANK_IN.equals(ret_prd_info.getBnk_flg())){
				gszMsgBuf = "产品 [" + ret_prd_info.getPrd_seq_id() + "] 已经在制保留";
				return new SimpleRtnBeen(E_FPPPNLOUT_PRD_ALREADY_IN_BOX, gszMsgBuf);
			}

			//检查该片玻璃是否被拿出做offline抽检 important
			if(ret_prd_info.getPrd_in_out_flg() != null && ret_prd_info.getPrd_in_out_flg().equals(_YES)){
				gszMsgBuf = "该片玻璃["+ret_prd_info.getPrd_seq_id()+"]已经被取出做Offline抽检了，请确认！";
				return new SimpleRtnBeen(E_FPPPNLOUT_PRD_IS_OUT, gszMsgBuf);
			}
			rtnBeen = checkBoxMix(ret_prd_info, ret_prd_infos);
			if (rtnBeen.getlRc() != _NORMAL) {
				return rtnBeen;
			}
			ret_prd_info.setPv_slot_no(ret_prd_info.getSlot_no());
			//set slot_no
			if(inTrx.getOpi_ope_flg()== null || !inTrx.getOpi_ope_flg().equals(_YES)){
				//TODO:检查该slot_no是否有玻璃
				String hql = "From Ret_prd_info where box_id_fk ='" +ret_box.getBox_id() +"'"
						+" and slot_no ='" + iaryA.getSlot_no()+"'";
				List<Ret_prd_info> ret_prd_infos2= retPrdInfoDao.find(hql);
				if(!ret_prd_infos2.isEmpty()){
					gszMsgBuf = "箱子 [" + ret_box.getBox_id() + "]子格位["+iaryA.getSlot_no()+"]已有玻璃！";
					return new SimpleRtnBeen(E_FPPPNLOUT_SLOT_IS_NOT_EMPTY, gszMsgBuf);
				}
				ret_prd_info.setSlot_no(iaryA.getSlot_no());

			}else{
//				TODO:从表中计算slot_no
				String slot_no = creatNewSlotNo(inTrx);
				ret_prd_info.setSlot_no(slot_no);
			}
			//set OX,Grade,ins flag, repair flag
			if(StringUtils.isNotBlank(iaryA.getChip_grade())){
				ret_prd_info.setChip_grade(iaryA.getChip_grade());//TODO:需要修改
				if(!iaryA.getChip_grade().contains("C")){
					ret_prd_info.setPrd_grade(_OK);
				}else if(!iaryA.getChip_grade().contains("A")){
					ret_prd_info.setPrd_grade(_NG);
				}else{
					ret_prd_info.setPrd_grade(_OKB);
				}
			}
			if(StringUtils.isNotBlank(iaryA.getInspection_flg())){
				ret_prd_info.setInspection_flg(iaryA.getInspection_flg());
			}else{
				ret_prd_info.setInspection_flg(_YES);//默认检测过
			}
			if(StringUtils.isNotBlank(iaryA.getRepair_flg())){
				ret_prd_info.setRepair_flg(iaryA.getRepair_flg());
			}else{
				ret_prd_info.setRepair_flg(_NO);//默认无需修补
			}
			if(StringUtils.isNotBlank(iaryA.getCid_id())){
				ret_prd_info.setIto_cid(iaryA.getCid_id());
			}
			if(StringUtils.isNotBlank(iaryA.getAbnormal_flg())){
				ret_prd_info.setAbnormal_flg(iaryA.getAbnormal_flg());
			}
			ret_prd_info.setBnk_flg(BANK_OUT);
			ret_prd_info.setBox_id_fk(inTrx.getBox_id());
			ret_prd_info.setTool_id_fk(inTrx.getTool_id());
			ret_prd_info.setTool_port_id_fk(inTrx.getTool_port_id());
			ret_prd_info.setPv_prd_grade(ret_prd_info.getPrd_grade());
			ret_prd_info.setEvt_usr(inTrx.getEvt_usr());
			ret_prd_info.setEvt_timestamp(gEvtTimestamp);
			ret_prd_info.setEvt_seq_id(gEvtSeqID);
			ret_prd_info.setEvt_cate(EVT_PNL_MOVE_OUT);

			if(inTrx.getSht_ope_msg() != null){
				ret_prd_info.setSht_ope_msg(inTrx.getSht_ope_msg());
			}else{
				ret_prd_info.setSht_ope_msg(_SPACE);
			}

			/**
			 * BM站存储厂内玻璃ID与客户玻璃ID
			 */
			if(ret_prd_info.getCr_tool_run_mode().equals(TOOL_RUN_MODE_BM)){
				Ret_prd_info  real_prd = (Ret_prd_info) ret_prd_info.clone();
				//厂内玻璃ID
				if(StringUtils.isNotBlank(iaryA.getReal_prd_seq_id())){
					real_prd.setPrd_seq_id(iaryA.getReal_prd_seq_id());
					//客户玻璃ID
					if(StringUtils.isNotBlank(iaryA.getCus_prd_seq_id())){
						real_prd.setCus_sn(iaryA.getCus_prd_seq_id());
					}
					real_prd.setTemp_prd_seq_id(ret_prd_info.getPrd_seq_id());
					//删除虚拟ID
					retPrdInfoDao.delete(ret_prd_info);
					retPrdInfoDao.save(real_prd);
				}else{
					retPrdInfoDao.update(ret_prd_info);
				}
			}else{
				retPrdInfoDao.update(ret_prd_info);
			}
			chip_qty += ret_prd_info.getPrd_qty();
		}
		rtnBeen.setObj(chip_qty);
		return rtnBeen;
	}


	/**
	 * Create New Slot No
	 * @param slot_no_max
	 * @return
	 */
	private String creatNewSlotNo(FpppnloutI inTrx){
		String slot_no_max = "", slot_no = "";
		int slot_no_max_int = 0, slot_no_new_int = 0;
		String sql = "SELECT MAX(SLOT_NO) From Ret_prd_info WHERE BOX_ID_FK='"+inTrx.getBox_id()+"'";
		List<String> objlist = retPrdInfoDao.findBySQL(sql);
		if(objlist.get(0) == null || objlist.size()==0){
			slot_no = "01";
		}else{
			slot_no_max = objlist.get(0);
			slot_no_max_int = Integer.valueOf(slot_no_max);
			slot_no_new_int = slot_no_max_int + 1;
			slot_no = String.format("%02d", slot_no_new_int);
		}

		return slot_no;
	}
	/**
	 * Update prd info -> into box
	 * @param inTrx
	 * @param gEvtTimestamp
	 *
	 * @return
	 */
	private SimpleRtnBeen updateRetBoxInfo(Ret_box ret_box, FpppnloutI inTrx, Timestamp gEvtTimestamp) {
		String gszMsgBuf = "";
		List<Ret_prd_info> ret_prd_infoList = new ArrayList<Ret_prd_info>();
		ret_prd_infoList = retPrdInfoDao.getShtListInfo(ret_box.getBox_id());
		if (ret_prd_infoList == null || ret_prd_infoList.size() ==0) {
			gszMsgBuf = "No prd in inMsg, should not happen!";
			return new SimpleRtnBeen(E_FPPPNLOUT_PRD_LIST_NULL, gszMsgBuf);
		}

		ret_box.setPrd_qty(ret_box.getPrd_qty() + inTrx.getPrd_cnt());
		if (1 <= ret_box.getPrd_qty()) {
			ret_box.setReal_emp(EXIST_CARRIER);
		}
		if(ret_box.getBox_stat().equals(PROC_EMPTY)){
			ret_box.setBox_stat(PROC_IN_PROCESS);
		}
		ret_box.setBnk_flg(BANK_OUT);
		ret_box.setWo_id_fk(ret_prd_infoList.get(0).getWo_id_fk());
		ret_box.setMdl_id_fk(ret_prd_infoList.get(0).getMdl_id_fk());
		ret_box.setGroup_id(ret_prd_infoList.get(0).getGroup_id());//修改箱子的组代码
		ret_box.setTool_id_fk(inTrx.getTool_id());
		ret_box.setTool_port_id_fk(inTrx.getTool_port_id());
		ret_box.setEvt_cate(EVT_PNL_MOVE_OUT);
		ret_box.setEvt_usr(inTrx.getEvt_usr());
		ret_box.setEvt_timestamp(gEvtTimestamp);
		retBoxDao.update(ret_box);
//		retPrdInfoDao.saveOrUpdateAll(ret_prd_infoList);

		return new SimpleRtnBeen(_NORMAL);
	}
	/**
	 * Check CST Category
	 * @param ret_box
	 * @return
	 */
	private SimpleRtnBeen checkCstCate4Ope(Ret_box ret_box, String tool_id){
		String gszMsgBuf ="";
		//Check packing tool
		Ret_tool_st ret_tool_st = retToolStDao.get(tool_id);
		if(ret_tool_st == null){
			gszMsgBuf = "该设备["+tool_id+"状态信息不存在，请确认！";
			return new SimpleRtnBeen(E_RET_TOOL_ST + E_READ_NOT_FOUND, gszMsgBuf);
		}
		if(ret_tool_st.getTool_run_mode().trim().equals(TOOL_RUN_MODE_PACK)){
			if(!ret_box.getBox_cate().trim().equals(BOX_CATE_PPBX)){
				gszMsgBuf = "该设备["+tool_id+"]Unload的卡匣["+ret_box.getBox_id()+"]类型["+ret_box.getBox_cate()+"]不符，"
						+ "应该为[PPBX],请检查！";
				return new SimpleRtnBeen(E_FPPVRFYPRO_BOX_CATE_UNMATCH, gszMsgBuf);
			}
		}
		//Check Other Tool
		if(!ret_tool_st.getTool_run_mode().trim().equals(TOOL_RUN_MODE_PACK)){
			if(!ret_box.getBox_cate().trim().equals(BOX_CATE_WCST)){
				gszMsgBuf = "该设备["+ret_tool_st+"]Unload的卡匣["+ret_box.getBox_id()+"]类型["+ret_box.getBox_cate()+"]不符，"
						+ "应该为[WCST],请检查！";
				return new SimpleRtnBeen(E_FPPVRFYPRO_BOX_CATE_UNMATCH, gszMsgBuf);
			}
		}
		return new SimpleRtnBeen(_NORMAL);
	}
	private SimpleRtnBeen checkBoxMix(Ret_prd_info ret_prd_info, List<Ret_prd_info> ret_prd_infoList) {
		String gszMsgBuf = "";
		// Get prd info
		if(ret_prd_infoList != null){
			for(int i=0; i<ret_prd_infoList.size();i++){
				// Proc info
				if (!ret_prd_info.getNx_proc_id_fk().equals(
						ret_prd_infoList.get(i).getNx_proc_id_fk())) {
					gszMsgBuf = "玻璃的下一制程不能混！ [" + ret_prd_info.getPrd_seq_id() + "]["
							+ ret_prd_info.getNx_proc_id_fk() + "] vs ["
							+ ret_prd_infoList.get(i).getPrd_seq_id() + "]["
							+ ret_prd_infoList.get(i).getNx_proc_id_fk() + "] ";
					return new SimpleRtnBeen(SHT_NX_PROC_ID_MIX, gszMsgBuf);
				}
				if (!ret_prd_info.getCr_proc_id_fk().equals(
						ret_prd_infoList.get(i).getCr_proc_id_fk())) {
					gszMsgBuf = "玻璃的当前制程不能混！[" + ret_prd_info.getPrd_seq_id() + "]["
							+ ret_prd_info.getCr_proc_id_fk() + "] vs ["
							+ ret_prd_infoList.get(i).getPrd_seq_id() + "]["
							+ ret_prd_infoList.get(i).getCr_proc_id_fk() + "] ";
					return new SimpleRtnBeen(SHT_CR_PROC_ID_MIX, gszMsgBuf);
				}

				if (!ret_prd_info.getMdl_id_fk().equals(
						ret_prd_infoList.get(i).getMdl_id_fk())) {
					gszMsgBuf = "玻璃的产品ID不能混！[" + ret_prd_info.getPrd_seq_id() + "]["
							+ ret_prd_info.getMdl_id_fk() + "] vs ["
							+ ret_prd_infoList.get(i).getPrd_seq_id() + "]["
							+ ret_prd_infoList.get(i).getMdl_id_fk() + "] ";
					return new SimpleRtnBeen(SHT_MDL_ID_MIX, gszMsgBuf);
				}

				// Path in
				if (!ret_prd_info.getNx_path_id_fk().equals(
						ret_prd_infoList.get(i).getNx_path_id_fk())) {
					gszMsgBuf = "玻璃的下一工艺路线不能混！[" + ret_prd_info.getPrd_seq_id()
							+ "][" + ret_prd_info.getNx_path_id_fk() + "] vs ["
							+ ret_prd_infoList.get(i).getPrd_seq_id() + "]["
							+ ret_prd_infoList.get(i).getNx_path_id_fk() + "] ";
					return new SimpleRtnBeen(SHT_PATH_ID_MIX, gszMsgBuf);
				}
				if (!ret_prd_info.getNx_path_ver_fk().equals(
						ret_prd_infoList.get(i).getNx_path_ver_fk())) {
					gszMsgBuf = "玻璃的下一工艺路线版本不能混！ [" + ret_prd_info.getPrd_seq_id()
							+ "][" + ret_prd_infoList.get(0).getNx_path_ver_fk() + "] vs ["
							+ ret_prd_infoList.get(i).getPrd_seq_id() + "]["
							+ ret_prd_infoList.get(i).getNx_path_ver_fk() + "] ";
					return new SimpleRtnBeen(SHT_PATH_VER_MIX, gszMsgBuf);
				}
				if (!ret_prd_info.getNx_ope_id_fk().equals(
						ret_prd_infoList.get(i).getNx_ope_id_fk())) {
					gszMsgBuf = "玻璃的下一站点ID不能混！ [" + ret_prd_info.getPrd_seq_id()
							+ "][" + ret_prd_info.getNx_ope_id_fk() + "] vs ["
							+ ret_prd_infoList.get(i).getPrd_seq_id() + "]["
							+ ret_prd_infoList.get(i).getNx_ope_id_fk() + "] ";
					return new SimpleRtnBeen(SHT_OPE_ID_MIX, gszMsgBuf);
				}
				if (!ret_prd_info.getNx_ope_no_fk().equals(
						ret_prd_infoList.get(i).getNx_ope_no_fk())) {
					gszMsgBuf = "玻璃的下一站点编号不能混！ [" + ret_prd_infoList.get(0).getPrd_seq_id()
							+ "][" + ret_prd_infoList.get(0).getNx_ope_no_fk() + "] vs ["
							+ ret_prd_infoList.get(i).getPrd_seq_id() + "]["
							+ ret_prd_infoList.get(i).getNx_ope_no_fk() + "] ";
					return new SimpleRtnBeen(SHT_OPE_NO_MIX, gszMsgBuf);
				}
				if (!ret_prd_info.getNx_ope_ver_fk().equals(
						ret_prd_infoList.get(i).getNx_ope_ver_fk())) {
					gszMsgBuf = "玻璃的下一站点版本不能混！[" + ret_prd_info.getPrd_seq_id()
							+ "][" + ret_prd_info.getNx_ope_ver_fk() + "] vs ["
							+ ret_prd_infoList.get(i).getPrd_seq_id() + "]["
							+ ret_prd_infoList.get(i).getNx_ope_ver_fk() + "] ";
					return new SimpleRtnBeen(SHT_OPE_VER_MIX, gszMsgBuf);
				}

				// Tool info
				if (!ret_prd_info.getNx_tool_run_mode().equals(
						ret_prd_infoList.get(i).getNx_tool_run_mode())) {
					gszMsgBuf = "玻璃的设备运行模式不能混！[" + ret_prd_info.getPrd_seq_id() + "]["
							+ ret_prd_info.getNx_tool_run_mode() + "] vs ["
							+ ret_prd_infoList.get(i).getPrd_seq_id() + "]["
							+ ret_prd_infoList.get(i).getNx_tool_run_mode() + "] ";
					return new SimpleRtnBeen(SHT_NX_TOOL_RUN_MODE_MIX, gszMsgBuf);
				}
				//rework count
				if(Integer.valueOf(ret_prd_infoList.get(0).getPrd_pf_cnt()) != Integer.valueOf(ret_prd_infoList.get(i).getPrd_pf_cnt()) ){
					gszMsgBuf = "玻璃的拔膜次数不能混！ [" + ret_prd_info.getPrd_seq_id() + "]["
							+ ret_prd_info.getPrd_pf_cnt() + "] vs ["
							+ ret_prd_infoList.get(i).getPrd_seq_id() + "]["
							+ ret_prd_infoList.get(i).getPrd_pf_cnt() + "] ";
					return new SimpleRtnBeen(SHT_PF_COUNT_MIX, gszMsgBuf);
				}
				Ret_wo ret_wo = retWoDao.getWithLock(ret_prd_info.getWo_id_fk(), LockMode.UPGRADE);
				if (null == ret_wo) {
					gszMsgBuf = "工单号 [" + ret_prd_infoList.get(0).getWo_id_fk() + "] 不存在!";
					return new SimpleRtnBeen(E_RET_WO + E_READ_NOT_FOUND, gszMsgBuf);
				}

				// WO info
				if (!ret_prd_info.getWo_id_fk().equals(
						ret_prd_infoList.get(i).getWo_id_fk())) {
					gszMsgBuf = "玻璃的工单号不能混！ [" + ret_prd_info.getPrd_seq_id() + "]["
							+ ret_prd_info.getWo_id_fk() + "] vs ["
							+ ret_prd_infoList.get(i).getPrd_seq_id() + "]["
							+ ret_prd_infoList.get(i).getWo_id_fk() + "] ";
					return new SimpleRtnBeen(SHT_WO_ID_MIX, gszMsgBuf);
				}
				//Check prd grade mix or not
				if( ret_prd_info.getCr_tool_run_mode().equals(TOOL_RUN_MODE_INS)||
						ret_prd_info.getCr_tool_run_mode().equals(TOOL_RUN_MODE_PACK)){//INS 最终检检查 && Packing
					if(!ret_prd_info.getPrd_grade().equals(ret_prd_infoList.get(i).getPrd_grade())){
						gszMsgBuf = "INS或包装出账时，玻璃等级不可以混！ [" + ret_prd_infoList.get(0).getPrd_grade() + "]VS["
								+ ret_prd_infoList.get(i).getPrd_grade() + "]";
						return new SimpleRtnBeen(PRD_GRADE_MIX, gszMsgBuf);
					}
				}
			}
		}
		return new SimpleRtnBeen(_NORMAL);
	}
}
